package web.action;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import nosql.MysqlConnector;
import nosql.query.ConditionRecommender;
import nosql.query.CriteriaException;
import nosql.query.FilterRecommender;
import nosql.query.NosqlQuery;
import nosql.query.NosqlStatement;
import nosql.query.Recommender;
import nosql.util.ComponentScore;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;

public class PageAction extends ActionSupport{
	private static MysqlConnector connector;
	private static NosqlStatement statement;
	
	private JSONArray jsonArrayproperties;
	private JSONArray sideBar;
	
	private String queryConditionString;	//	selected query condition, in form of a op v1,b op v2, ...
	private String selectedConditionString;	//	selected query condition properties, in form of a,b,c,...
	private String filterString;			//	selected query properties, in form of a,b,c,...
	private String queryConditions;	//	queryConditions, in form of JSON
	
	private JSONArray recommendedConditions;	//	returned recommended conditions
	private JSONArray queryResult;			//	entity query result
	private JSONArray recommendedFilters;	//	returned recommended filters

	
	public String getQueryConditions() {
		return queryConditions;
	}

	public void setQueryConditions(String queryConditions) {
		this.queryConditions = queryConditions;
	}

	public JSONArray getProperties() {
		return jsonArrayproperties;
	}

	public JSONArray getRecommendedConditions() {
		return recommendedConditions;
	}
	
	public JSONArray getRecommendedFilters(){
		return recommendedFilters;
	}

	public String getSelectedConditionString() {
		return selectedConditionString;
	}

	public void setSelectedConditionString(String selectedConditionString) {
		this.selectedConditionString = selectedConditionString;
	}

	public JSONArray getQueryResult() {
		return queryResult;
	}

	public JSONArray getSideBar() {
		return sideBar;
	}
	
	public String getQueryConditionString() {
		return queryConditionString;
	}

	public void setQueryConditionString(String queryConditionString) {
		this.queryConditionString = queryConditionString;
	}

	public String getFilterString() {
		return filterString;
	}

	public void setFilterString(String filterString) {
		this.filterString = filterString;
	}



	public String initPage() throws SQLException, IOException, URISyntaxException{
		String url = "jdbc:mysql://localhost:3306";
		
		String path = (getClass().getClassLoader().getResource("").toURI()).getPath();
		FileInputStream inputStream = new FileInputStream(path + "/config.properties");
		Properties properties = new Properties();
		properties.load(inputStream);
		url += "/" + properties.getProperty("database");
		System.out.println("Connect to " + url);
		
		connector = MysqlConnector.getInstance(url, "dev", "dev");
		statement = new NosqlStatement(connector);
		
		Set<String> propertySet = connector.getAllPropertyTableName();
		JSONArray json = new JSONArray();
		for(String propertyName : propertySet){
			json.add(propertyName);
		}
		
		jsonArrayproperties = json;
		return Action.SUCCESS;
	}
	
	/**
	 * 
	 * @return whether the query success
	 * @throws SQLException
	 * @throws CriteriaException
	 */
	public String query() throws CriteriaException{
		try{
			NosqlQuery query = statement.createQuery();
			String[] properties = filterString.split(",");
			if(properties.length == 0){
				Set<String> propSet = connector.getAllPropertyTableName();
				properties = (String[])propSet.toArray();
			}
			List<String> listProperty = new ArrayList<String>();
			for(String property : properties){
				listProperty.add(property);
			}
			System.out.println("query...");
			List<String> list = query.query(queryConditionString, listProperty).getJSON();
			JSONArray array = new JSONArray();
			for(String s : list){
				System.out.println(s);
				array.add(s);
			}
			queryResult = array;
		} catch(SQLException e){
			e.printStackTrace();
		}
		return Action.SUCCESS;
	}
	
	public String updateConditionList(){
		String[] properties = filterString.split(",");
		if(filterString.length() == 0)
			properties = null;
		
		JSONParser parser = new JSONParser();
		JSONArray queryConditionJSONArray = null;
		if(queryConditions.length() != 0){
			try{
				Object obj = parser.parse(queryConditions);
				if(obj instanceof JSONArray){
					queryConditionJSONArray = (JSONArray)obj;
				}
			}catch(ParseException e){
				e.printStackTrace();
			}
		}
		
		Recommender recom = new ConditionRecommender(connector, 2);
		List<ComponentScore> componentScoreList = recom.getScores(properties, queryConditionJSONArray);
		recommendedConditions = new JSONArray();
		for(ComponentScore score : componentScoreList){
			JSONObject condObject = new JSONObject();
			condObject.put("name", score.getFirst());
			condObject.put("score", score.getSecond());
			recommendedConditions.add(condObject);
		}
		
		return Action.SUCCESS;
	}
	
	public String updateFilterList(){
		String[] properties = filterString.split(",");
		if(filterString.length() == 0)
			properties = null;
		
		JSONParser parser = new JSONParser();
		JSONArray queryConditionJSONArray = null;
		if(queryConditions.length() != 0){
			try{
				Object obj = parser.parse(queryConditions);
				if(obj instanceof JSONArray){
					queryConditionJSONArray = (JSONArray)obj;
				}
			}catch(ParseException e){
				e.printStackTrace();
			}
		}
		
		Recommender recom = new FilterRecommender(connector, 1);
		List<ComponentScore> componentScoreList = recom.getScores(properties, queryConditionJSONArray);
		recommendedFilters = new JSONArray();
		for(ComponentScore score : componentScoreList){
			JSONObject filterObject = new JSONObject();
			filterObject.put("name", score.getFirst());
			filterObject.put("score", score.getSecond());
			recommendedFilters.add(filterObject);
		}
		
		return Action.SUCCESS;
	}
}
